home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Documentation / Tech Notes & Articles / Recipes / Storage / Persistent Reference < prev    next >
Encoding:
Text File  |  1995-07-11  |  5.4 KB  |  167 lines  |  [TEXT/ttxt]

  1. OpenDoc™ Recipes
  2.  
  3.  
  4. Persistent References
  5. By The OpenDoc Design Team
  6. July 11, 1995.
  7.  
  8.  
  9. © 1993-1995  Apple Computer, Inc. All Rights Reserved.
  10. Apple, the Apple logo, and Macintosh are registered trademarks of Apple Computer, Inc.
  11. Mac and OpenDoc are trademarks of Apple Computer, Inc. 
  12.  
  13. Changes since DR2
  14.  
  15. 1) Corrected usage of ODStorageUnit::GetStrongStorageUnitRef and GetWeakStorageUnitRef.
  16. 2) Fixed parameter passing errors of GetValue and SetValue.
  17.  
  18. Overview
  19.  
  20. A Persistent Reference is used in a Storage Unit Value to refer to another Storage Unit in the same Document. This Reference is persistent in the sense that it is preserved across sessions.
  21.  
  22. References are used in many places in OpenDoc:
  23.  
  24. 1)     The Draft has a list of references to the root frames. When a Draft is opened,  the root parts can use the frames to construct their windows.
  25.  
  26. 2)    Frame has a Persistent Reference to its Part and the Part in turn has a Persistent     Reference to its Display and Embedded Frames. Persistent References to Embedded Frames are essential to part embedding.
  27.  
  28. 3)    Parts need Persistent References for hierarchical storage.
  29.  
  30. The following is a (simplified) diagram of what the persistent objects in an OpenDoc Document relate to each other (with arrows being Persistent References):
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42. ODStorageUnitRef
  43.  
  44. This Persistent Reference  in OpenDoc is typed ODStorageUnitRef. ODStorageUnitRef is a 32-bit value. One should never try to inspect or interpret a ODStorageUnitRef. ODStorageUnit and ODStorageUnitView provides a set of methods to manipulate ODStorageUnitRef.
  45.     
  46. void    GetStrongStorageUnitRef(ODStorageUnit* embeddedSU, ODStorageUnitRef ref);
  47.  
  48. void    GetWeakStorageUnitRef(ODStorageUnit* embeddedSU, ODStorageUnitRef ref);
  49.  
  50. ODBoolean        IsStrongStorageUnitRef(ODStorageUnitRef ref);
  51.  
  52. ODBoolean        IsWeakStorageUnitRef(ODStorageUnitRef ref);
  53.  
  54. ODStorageUnit*    RemoveStorageUnitRef(ODStorageUnitRef ref);
  55.  
  56. ODStorageUnitID    GetIDFromStorageUnitRef(ODStorageUnitRef ref);
  57.  
  58. ODBoolean        IsValidStorageUnitRef(ODStorageUnitRef ref);
  59.  
  60.  
  61. ODStorageUnitRef can only be created from a ODStorageUnit which is focused to a Value or a ODStorageUnitView (is to be focused to a Value). The scope of the ODStorageUnitRef is then limited to the Value from which it is created. It is illegal and dangerous to use ODStorageUnitRef in a different Value. It will almost certainly not refer to the correct Storage Unit rendering the resulting behavior unpredictable.
  62.  
  63. One can create virtually unlimited number of References in a Storage Unit Value.
  64.  
  65. If a Persistent Reference is no longer needed, one should remove it from the Value from which it is created. It is crucial to have unnecessary Persistent References removed for efficiency,  robustness and effective garbage collection.
  66.  
  67. ODStorageUnitRef is not recycled. Therefore, all ODStorageUnitRefs from a Value are guaranteed to be unique.
  68.  
  69. The “referring power” of ODStorageUnitRef are preserved across sessions. One can write out a ODStorageUnitRef in the Value, close and reopen the Container and use the ODStorageUnitRef in that Value to find the referred Storage Unit.
  70.  
  71. Strong and Weak ODStorageUnitRef
  72.  
  73. There are two kinds of ODStorageUnitRef -- strong and weak. Their difference is important when a Clone operation is performed (using ODDraft::BeginClone and ODDraft::EndClone). In a Clone operation, all the Storage Units referenced by a Strong ODStorageUnitRef are copied. Consider the following example,
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.      
  86. If we clone A, all 4 Storage Units are copied.
  87. If we clone B, only B, C and D are copied.
  88. If we clone C, only C and D are copied.
  89. If we clone D, only C and D are copied.
  90.  
  91.  
  92. Examples
  93.  
  94. Creating an Auxillary Storage Unit for a Part:
  95.  
  96. void MyPart::InitPart(Environment* ev, ODStorageUnit* storageUnit)
  97. {
  98.     ......
  99.     
  100.     // Create the Aux Storage Unit
  101.  
  102.     ODStorageUnit* auxStorageUnit = 
  103.             storageUnit->GetDraft(ev)->CreateStorageUnit(ev);
  104.  
  105.     // Add a Property and Value to store the Persistent Reference
  106.  
  107.  storageUnit->AddProperty(ev, kODPropContents);
  108.     storageUnit->AddValue(ev, kODStrongStorageUnitRef);
  109.  
  110.     // Note that storageUnit is focused to the newly created value
  111.     // already.
  112.     // Create a Persistent Reference to the Aux Storage Unit in the
  113.     // context of the create Value.
  114.  
  115.     ODStorageUnitRef ref;
  116.     storageUnit->GetStrongStorageUnitRef(ev, auxStorageUnit, ref);
  117.     
  118.     // Note that the focus is unchanged and it is still pointing to the
  119.     // created Value.
  120.     // Write out the Persistent Reference to the Value.
  121.  
  122.  ODByteArray ba;
  123.  ba._length = sizeof(ODStorageUnitRef);
  124.  ba._maximum = sizeof(ODStorageUnitRef);
  125.  ba._buffer = &ref;
  126.  storageUnit->SetValue(ev, &ba);
  127.  
  128.     ......
  129. }
  130.  
  131. Let’s say that the Part is instantiated later in a different session, the Part can retrieve its Auxillary Storage Unit as follows:
  132.  
  133. void MyPart::InitPartFromStorage(Environment* ev, ODStorageUnit* storageUnit)
  134. {
  135.     ......
  136.     // Focus the Storage Unit to the right Value.
  137.  
  138.     storageUnit->Focus(
  139.                     ev,
  140.                     kODPropContents,
  141.                     kODPosUndefined,
  142.                     kODStrongStorageUnitRef,
  143.                     0,
  144.                     kODPosUndefined);
  145.  
  146.     // Retrieve the Persistent Reference
  147.  
  148.     ODByteArray ba;
  149.     storageUnit->GetValue(ev, sizeof(ODStorageUnitRef), &ba);
  150.  
  151.     // Use the retrieved Persistent Reference to get the ID for the
  152.     // Storage Unit.
  153.  
  154.     ODStorageUnitID id = storageUnit->GetIDFromStorageUnitRef(ev, *((ODStorageUnitRef*) ba._buffer));
  155.  
  156.     // Dispose of the buffer
  157.     ODDisposePtr(ba._buffer);
  158.  
  159.     // Use the id to get the Aux Storage Unit from the Draft.
  160.  
  161.     ODStorageUnit* auxStorageUnit =
  162.             storageUnit->GetDraft(ev)->GetStorageUnit(ev, id);
  163.  
  164.     ......
  165.  
  166. }
  167.